# -*- coding: utf-8 -*-
import requests
import json
import time
import base64
import numpy as np
import cv2
import faceToolsV2
# import dnnDetect
import faceTools
import getface
from redis_ import RedisClient
from mongo_ import MyMongoClient

with open('../config.py', 'r', encoding="utf-8") as conf_r:
    exec(conf_r.read())


box_ip = None
box_port = None
mongo_host = mongoinfo['ip']
mongo_port = mongoinfo['port']
redis_ip = redisinfo['ip']
redis_port = redisinfo['port']
redis_password = redisinfo['password']
ovo_ip = ovoinfo['ip']
ovo_port = ovoinfo['port']
ovo_whether = ovoinfo['whether_do']

# 初始化mongo client
mongo_client = MyMongoClient(mongo_host, mongo_port)
redis_client = RedisClient(redis_ip, redis_port, redis_password)


#
# ovo_ip = ovoinfo['ip']
# ovo_port = ovoinfo['port']


#  ovo函数  获取图片的函数   插入redis和mongo的函数


def strtoimg(str):
    # base64--np
    imgData = base64.b64decode(str)
    nparr = np.frombuffer(imgData, np.uint8)
    img_np = cv2.imdecode(nparr, cv2.IMREAD_COLOR)
    return img_np


def get_f(imgbase64):
    # 获取特征值
    # return ovn_f
    url = 'http://{}:{}/getbigf'.format(ovo_ip, ovo_port)
    data = {
        'base64': imgbase64
    }
    try:
        r = requests.post(url, json.dumps(data))
        # print(r.text)

        res = json.loads(r.text)
        return res['f']
    except:
        time.sleep(2)
        return ''


def ovo(a_base64_f, b_base64_f):
    # yituovo
    # # hit_image_yitu_171_feature_base64 = img_hit['yitu_171_feature_base64']
    # # ovo_rtn = yituydn.ovo(face_yitu_171_feature_base64, hit_image_yitu_171_feature_base64)
    # # if ovo_rtn['rtn'] == 0:
    # #     new_similarity = ovo_rtn['similarity']
    # # else:
    # #     new_similarity = -1
    # 1.40 ovo
    # print(a_base64_f)
    # print(b_base64_f)

    if a_base64_f == '' or b_base64_f == '':
        return -1

    url = 'http://{}:{}/faceoof'.format(ovo_ip, ovo_port)
    data = {
        "a": a_base64_f,
        "b": b_base64_f
    }
    try:
        r = requests.post(url, json.dumps(data))
        # print(r.text)

        res = json.loads(r.text)
        return res['similarity']
    except:
        time.sleep(2)
        return -1


def detect_front(detectFacev2, detectCount, detectFaceV1):
    if detectFaceV1['detectFace'] == 1:
        if detectFacev2 != 1 or detectCount >= 2 or abs(detectFaceV1['x']) > 40 or abs(
                detectFaceV1['y']) > 40 or abs(detectFaceV1['z']) > 40:
            return False
        else:
            return True
    else:
        return False


def insert_redis_mongo(images, data_dic):
    dets = getface.detall(images)
    img, s = getface.getface(images)
    if (img is not None) and len(img) != 0:
        try:
            detectFacev2 = int(faceToolsV2.detect_(img))
        except:
            detectFacev2 = 0

        # detectCount = dnnDetect.detect_(images)
        detectCount = len(dets)
        detectFaceV1 = faceTools.detect_(img)
    else:
        detectFacev2 = int(0)
        detectCount = int(9)
        detectFaceV1 = {
            'detectFace': int(0)
        }

    # print(detectFacev2)
    is_front = detect_front(detectFacev2, detectCount, detectFaceV1)

    # 入db15
    db15_data = {
        'camera_id': data_dic['camera_id'],
        'face_image_id': data_dic['face_image_id'],
        'face_image_uri': data_dic['face_image_uri'],
        'picture_uri': data_dic['picture_uri'],
        'timestamp': data_dic['timestamp'],
        '_id': data_dic['face_image_id'],
        'hezi_guidang_ip': data_dic['hezi_guidang_ip'],
        'detectFacev2': detectFacev2,
        'detectCount': detectCount,
        'ovn_f': data_dic['ovn_f'],
        'is_front': is_front,
        'hezi_guidang_face_id': data_dic['hezi_guidang_face_id'],
        'hezi_guidang_repo_id': data_dic['hezi_guidang_repo_id']
    }

    if is_front:
        ovo_f = get_f(data_dic['face_base64'])
        db15_data.update({'ovo_f': ovo_f})

    db15_data.update(detectFaceV1)
    # 入redis
    for key in db15_data.keys():
        redis_client.insert_specific_data(data_dic['face_image_id'], key, str(db15_data[key]))
    # 入mongo

    # if 'face_base64' in data_dic:
    #     db15_data['face_base64'] = data_dic['face_base64']

    mongo_client.insert_cap(db15_data)
    return is_front


def get_ovncam_dic(similarity, hitface_id, camera_id, new_similarity, is_front):
    hit_dic = {
        'similarity': similarity,
        'hit_face_image_id': hitface_id,
        'camera_id': camera_id,
        'ovo_similarity': new_similarity,
        'is_front': is_front
    }
    return hit_dic


def get_redis_f(img_hit):
    ovo_key_has = redis_client.has_h_key(img_hit['face_image_id'], 'ovo_f')
    hit_f_ovo_base64 = None
    if ovo_key_has:
        hit_f_ovo_base64 = redis_client.RDB_getFace(img_hit['face_image_id'])['ovo_f']

    if not ovo_key_has:
        return ''
        # hit_face_base64 = mongo_client.get_face_base64(img_hit['face_image_id'])['face_base64']
        #
        # hit_f_ovo_base64 = get_f(hit_face_base64)
        #
        # redis_client.insert_specific_data(img_hit['face_image_id'], 'ovo_f', hit_f_ovo_base64)
        # mongo_client.update_ovo(img_hit['face_image_id'], hit_f_ovo_base64)
    return hit_f_ovo_base64


def get_ovn_f(img_dic):
    if 'ovn_f' not in img_dic:
        img_dic['ovn_f'] = ''

    if img_dic['ovn_f'] is None:
        img_dic['ovn_f'] = ''


# logic主函数
def logic(face_img, cam_ovn, card_ovn):
    # face_img: {'hezi_guidang_face_id':, 'face_image_id': , 'timestamp': , 'hezi_guidang_face_id': , ovn_f, 'face_image_uri': , 'camera_id': , 'picture_uri': , 'ovn_f': ,}
    # cam_ovn:[{'face_image_id': , 'camera_id': , 'similarity': , 'face_image_uri': , 'picture_uri': ,  'timestamp': , 'ip': , ovn_f}]
    # card_ovn:[{'face_image_id': , 'repository_id': , 'similarity': , 'face_image_uri': , 'picture_uri': ovn_f ,
    # 'name': , 'person_id': , 'timestamp': , 'ip': }]
    get_ovn_f(face_img)
    face_img_id = face_img['face_image_id']
    timestamp = face_img['timestamp']

    ebn_result = []

    face_has = redis_client.exists_id(face_img_id)

    face_image = strtoimg(face_img['face_base64'])

    if face_image is None:
        return

    if not face_has:
        face_front = insert_redis_mongo(face_image, face_img)

    else:
        redis_face_img = redis_client.RDB_getFace(face_img_id)
        face_front = redis_face_img['is_front']

    if ovo_whether:
        # 第一遍循环统计数据
        hit_face_acvs_dic = {}
        face_front_dic = {}
        acvs_list = []

        for img_hit in cam_ovn:
            get_ovn_f(img_hit)
            hit_face_id = img_hit['face_image_id']

            if hit_face_id == face_img_id:
                continue

            if face_front:
                hit_face_front = redis_client.RDB_getFace(hit_face_id)['is_front']
                face_front_dic[hit_face_id] = hit_face_front
                if hit_face_front:
                    hit_face_acvs_dic[hit_face_id] = []
                    redis_client.RDB_getfaceacvsall(hit_face_id, hit_face_acvs_dic, acvs_list, start=0, end=-1)

        # 统计
        if not face_front:
            for img_hit in cam_ovn:
                get_ovn_f(img_hit)
                similarity = img_hit['similarity']
                camera_id = img_hit['camera_id']
                hitface_id = img_hit['face_image_id']

                if hitface_id == face_img_id:
                    continue

                hitface_front = redis_client.RDB_getFace(hitface_id)['is_front']
                hit_dic = get_ovncam_dic(similarity, hitface_id, camera_id, 0, hitface_front)
                ebn_result.append(hit_dic)

        if face_front:
            # 第二遍插入数据
            for img_hitt in cam_ovn:
                get_ovn_f(img_hitt)
                acvs_tuple_list = []
                count_list = []
                similarity = img_hitt['similarity']
                camera_id = img_hitt['camera_id']
                hitface_id = img_hitt['face_image_id']
                if hitface_id == face_img_id:
                    continue

                # 97 98侧脸
                if hitface_id not in hit_face_acvs_dic:
                    # hitface_front = False
                    hit_dic = {
                        'similarity': similarity,
                        'hit_face_image_id': hitface_id,
                        'camera_id': camera_id,
                        'is_front': False
                    }
                    ebn_result.append(hit_dic)

                else:
                    hit_acvs_list = hit_face_acvs_dic[img_hitt['face_image_id']]
                    # 正脸没有档
                    if len(hit_acvs_list) == 0:

                        # ovo获取base64之前判断 db15 是否含有这个face_id

                        f_base64 = get_redis_f(face_img)
                        hit_f_base64 = get_redis_f(img_hitt)

                        new_similarity = ovo(f_base64, hit_f_base64)

                        # new_similarity = ovo(f_base64, hit_f_base64)   ############ 双向接口

                        hit_dic = get_ovncam_dic(similarity, hitface_id, camera_id, new_similarity,
                                                 face_front_dic[hitface_id])

                        hit_dic['acvs_id'] = acvs_tuple_list
                        ebn_result.append(hit_dic)
                    # 正脸有档
                    else:
                        for acvs_id in hit_acvs_list:
                            acvs_tuple_list.append((acvs_id, acvs_list.count(acvs_id)))
                            count_list.append(acvs_list.count(acvs_id))
                        count_max = max(count_list)
                        if count_max < 2:

                            f_base64 = get_redis_f(face_img)
                            hit_f_base64 = get_redis_f(img_hitt)

                            new_similarity = ovo(f_base64, hit_f_base64)

                            hit_dic = get_ovncam_dic(similarity, hitface_id, camera_id, new_similarity,
                                                     face_front_dic[hitface_id])
                            hit_dic['acvs_id'] = acvs_tuple_list
                            ebn_result.append(hit_dic)
                        else:
                            hit_dic = get_ovncam_dic(similarity, hitface_id, camera_id, count_max * 100,
                                                     face_front_dic[hitface_id])
                            hit_dic['acvs_id'] = acvs_tuple_list
                            ebn_result.append(hit_dic)
    if not ovo_whether:
        for img_hit in cam_ovn:
            get_ovn_f(img_hit)
            similarity = img_hit['similarity']
            camera_id = img_hit['camera_id']
            hitface_id = img_hit['face_image_id']

            if hitface_id == face_img_id:
                continue

            hitface_front = redis_client.RDB_getFace(hitface_id)['is_front']
            if not face_front:
                hit_dic = get_ovncam_dic(similarity, hitface_id, camera_id, 0, hitface_front)
            else:
                hit_dic = get_ovncam_dic(similarity, hitface_id, camera_id, 100, hitface_front)
                if not hitface_front:
                    hit_dic.pop('ovo_similarity')

            ebn_result.append(hit_dic)

    for card_hit_img in card_ovn:
        hit_card_id = card_hit_img['face_image_id']

        similarity = card_hit_img['similarity']
        repository_id = card_hit_img['repository_id']
        card_hit_dic = {
            'similarity': similarity,
            'hit_face_image_id': hit_card_id,
            'hit_repository_id': repository_id
        }

        ebn_result.append(card_hit_dic)

    ebn_result = sorted(ebn_result, key=lambda x: x['similarity'], reverse=True)

    ebndata = {
        "face_image_id": face_img_id,
        "result": ebn_result,
        "is_front": face_front,
        "timestamp": timestamp
    }
    # 插入ebn结果
    redis_client.insert_hit_data(json.dumps(ebndata))
